package com.frame.ar.hander;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;

import com.frame.ar.hander.DataXMLHander.Data;
import com.frame.ar.hander.DataXMLHander.Param;
import com.frame.ar.hander.DataXMLHander.When;
import com.frame.ar.util.MapUtil;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.justep.baas.data.Util;
import com.wxwyapp.config.DBSource;

/**
 * 作用描述：数据解析器
 * 
 * @author LRC
 * @createDate 2015年10月20日
 * @version v1.0
 * @updateRecord 格式：时间，作者，修改说明
 ** 
 * 
 */
public class DataHander {

	/**
	 * 功能描述：根据消息id，和传入参数获取消息实体
	 * 
	 * @createDate 2015年10月20日 by LRC
	 * @param dataId
	 * @param base
	 * @return
	 * @throws Exception
	 * @updateRecord 格式：时间，作者，修改说明
	 ** 
	 * 
	 */
	public static Object getData(String dataId, Map<String, Object> base)
			throws Exception {

		DataXMLHander config = DataXMLHander.getInstance();
		// 实时解析
		config.parse();
		// 获取消息模板对象
		Data data = config.getData(dataId);
		System.out.println("dataId = "+dataId);
		if (data == null)
			return null;
		// 初始化数据集合
		Map<String, Map<String, Object>> params = new HashMap<String, Map<String, Object>>();
		params.put("base", base);

		if (data.params != null && data.params.size() > 0) {
			for (Param param : data.params) {
				if ("db".equals(param.from)) {
					fillParamBySQL(param.sql, param, params);
				} else if ("list".equals(param.from)) {
					params.put(param.id, param.data);
				}
			}
		}

		Object returnValue = getRturn(data, params);
		
		return returnValue;
	}

	/**
	 * 功能描述：通过sql填充数据
	 * 
	 * @createDate 2015年10月21日 by LRC
	 * @param sql
	 * @param datas
	 * @updateRecord 格式：时间，作者，修改说明
	 ** 
	 * 
	 */
	public static void fillParamBySQL(String sql, Param param,
			Map<String, Map<String, Object>> datas) {
		// 判断sql的合法性
		if (sql == null || "".equals(sql.trim()))
			return;

		if (sql.indexOf("select") == -1)
			return;

		// 解析查询参数
		List<String[]> argNames = parseTXT(sql);
		String SQL = getSQL(sql);
		List<Object> args = new ArrayList<Object>();
		for (String[] arg : argNames) {
			String dataId = arg[0];
			String key = arg[1];
			Map<String, Object> data = datas.get(dataId);
			if (data != null) {
				args.add(data.get(key));
			} else {
				args.add(null);
			}
		}
		// 获取数据源
		String dbSource = param.dbSource;

		// 查询数据列表
		List<Record> rs = Db.use(dbSource).find(SQL,
				args.toArray(new Object[] {}));
		List<Map<String, Object>> _datas = MapUtil.getMapListFromRecord(rs);
		// 填充数据
		if (_datas.size() > 0) {
			if (_datas.size() >= param.rownum) {
				datas.put(param.id, _datas.get(param.rownum - 1));
			} else {
				datas.put(param.id, _datas.get(_datas.size() - 1));
			}
		}

	}

	/**
	 * 功能描述：解析sql获取查询参数名
	 * 
	 * @createDate 2015年10月21日 by LRC
	 * @return
	 * @updateRecord 格式：时间，作者，修改说明
	 ** 
	 * 
	 */
	public static List<String[]> parseTXT(String sql) {
		Pattern pattern = Pattern.compile("\\[([^\\[]*)\\]");
		Matcher matcher = pattern.matcher(sql);
		List<String[]> arr = new ArrayList<String[]>();
		while (matcher.find()) {
			String[] val;
			String txt = matcher.group(1);
			val = txt.split("\\.");
			arr.add(val);
		}
		return arr;
	}

	/**
	 * 功能描述：获取参数查询语句
	 * 
	 * @createDate 2015年10月21日 by LRC
	 * @return
	 * @updateRecord 格式：时间，作者，修改说明
	 ** 
	 * 
	 */
	public static String getSQL(String sql) {
		Pattern pattern = Pattern.compile("\\[([^\\[]*)\\]");
		Matcher matcher = pattern.matcher(sql);
		String sb = new String(sql);
		while (matcher.find()) {
			String txt = matcher.group(1);
			sb = sb.replaceAll("\\[" + txt + "\\]", "\\?");
		}
		return sb;
	}

	/**
	 * 功能描述：填充数据对象
	 * 
	 * @createDate 2015年10月21日 by LRC
	 * @param msg
	 * @param datas
	 * @return
	 * @updateRecord 格式：时间，作者，修改说明
	 ** 
	 * 
	 */
	public static Object getRturn(Data data,
			Map<String, Map<String, Object>> params) {
		// 将data填充大表达式
		JexlContext context = new MapContext();
		for (Entry<String, Map<String, Object>> d : params.entrySet()) {
			String id = d.getKey();
			Map<String, Object> value = d.getValue();
			context.set(id, value);
		}
		// 创建表达式解析器
		JexlEngine jexl = new JexlEngine();

		List<When> whens = data.value.whens;
		String from = null;
		System.out.println("params = " + params);
		for (When when : whens) {
			String jexlExp = when.express;
			Expression e = jexl.createExpression(jexlExp);
			Object o = e.evaluate(context);
			if (o instanceof Boolean) {
				// 判断表达式结果是否为true
				Boolean b = (Boolean) o;
				if (b != null && b == true) {
					System.out.println("when = " +jexlExp);
					from = when.sql;
					break;
				}
			}
		}
		//从列外中获取sql
		if(from==null){
			from = data.value.othersSql;
			System.out.println("others sql = " +from);
		}

		// 解析查询参数
		List<String[]> argNames = parseTXT(from);
		String columns = null;
		String FROM = getSQL(from);
		String SELECT;
		if(data.value.columns==null){
			//SELECT = "SELECT * ";
			SELECT = "";//直接从from中获取
			columns="*";
		}else{
			SELECT = "SELECT " + data.value.columns;
			columns = data.value.columns;
		}
		List<Object> sqlParams = new ArrayList<Object>();
		
		for (String[] arg : argNames) {
			String dataId = arg[0];
			String key = arg[1];
			Map<String, Object> param = params.get(dataId);
			if (param != null) {
				sqlParams.add(param.get(key));
			} else {
				sqlParams.add(null);
			}
		}
		// 获取数据源
		String dbSource = data.value.dbSource;

		String SQL = SELECT +" "+FROM; 
		System.out.println("SQL = " + SQL);
		System.out.println("sqlParams = " + sqlParams);
		Class type = data.value.type;
		if(type == com.justep.baas.data.Table.class){
			//返回BIZData table格式 的数据
			Object ooffset = params.get("base").get("offset");
			Object olimit = params.get("base").get("limit");
			Integer offset = olimit==null ? 0 : Integer.parseInt(ooffset.toString());
			Integer limit = olimit==null ? 10 : Integer.parseInt(olimit.toString());
			com.justep.baas.data.Table table = Util.queryData(dbSource, SQL, sqlParams, columns, offset, limit);
			//计算总数
			String count = data.value.count;
			if(count!=null){
				String jexlExp = count;
				Expression e = jexl.createExpression(jexlExp);
				Object oc = e.evaluate(context);
				if(oc!=null){
					Integer total = oc==null ? null : Integer.parseInt(oc.toString());
					table.setTotal(total);
				}
			}
			return table;
		}else if(type==com.jfinal.plugin.activerecord.Record.class){
			// 查询数据列表
			List<Record> rs = Db.use(dbSource).find(SQL,
					sqlParams.toArray(new Object[] {}));
			return rs;
		}if(type==java.lang.Integer.class){
			//判断操作类型
			if(!"find".equals(data.value.action)){
				//执行sql语句
				return Db.use(dbSource).update(SQL,
					sqlParams.toArray(new Object[] {}));
			}else{
				return null;
			}
		}else{
			// 查询数据列表
			List<Record> rs = Db.use(dbSource).find(SQL,
					sqlParams.toArray(new Object[] {}));
			return rs;
		}
	}

	public static void main(String[] args) {
//		String sql = "from vw_pms_bi_notice_byuser where publishTime is not null and  pid=[base.personId] order by publishTime desc";
//		List<String[]> arr = parseTXT(sql);
//		for (String[] ar : arr) {
//			System.out.println(Arrays.toString(ar));
//		}
//
//		System.out.println(sql);
//		System.out.println(getSQL(sql));
//		System.out.println(sql.replaceAll("\\[base.uname\\]", "?"));
		Map<String,Object> base = new HashMap<String,Object>();
		base.put("offset", 0);
		base.put("publishtime" ,null);
		JexlContext context = new MapContext();
		context.set("base", base);
		
		String jexlExp = "base['offset']==0 &&base['publishtime']==null ";
		JexlEngine jexl = new JexlEngine();
		Expression e = jexl .createExpression(jexlExp);
		Object o = e.evaluate(context);
		System.out.println(o);
	}
}

